import {Wall} from '../pos.js'
import {Grid} from '../pos.js'
import {Node} from './node.js'

export class Maze {
  constructor(grid_num) {
    this.free = 0
    this.busy = 1
    this.grid_num = grid_num
    this.tag = new Array()
    for (let i = 0; i < grid_num; i++) {
      let tmp = new Array()
      for (let j = 0; j < grid_num; j++) {
        tmp.push(this.free)
      }
      this.tag.push(tmp)
    }
    this.H = 0
    this.V = 1
    this.visited = new Array()
    let init_neighbors = new Array()
    init_neighbors.push(new Grid(1, 0))
    init_neighbors.push(new Grid(0, 1))
    let init_node = new Node(new Grid(0, 0), init_neighbors)
    this.visited.push(init_node)
    this.tag[0][0] = this.busy
    this.tag[0][1] = this.busy
    this.tag[1][0] = this.busy
  }

  _get_random(n) {
    return Math.floor(Math.random() * n)
  }

  _add_neighbor(neighbors, x, y) {
    neighbors.push(new Grid(x, y))
    this.tag[x][y] = this.busy
  }

  _get_neighbors(x, y) {
    let neighbors = new Array()
    if (y - 1 >= 0 && this.tag[x][y - 1] == this.free) {
      this._add_neighbor(neighbors, x, y - 1)
    }
    if (x + 1 <= this.grid_num - 1 && this.tag[x + 1][y] == this.free) {
      this._add_neighbor(neighbors, x + 1, y)
    }
    if (y + 1 <= this.grid_num - 1 && this.tag[x][y + 1] == this.free) {
      this._add_neighbor(neighbors, x, y + 1)
    }
    if (x - 1 >= 0 && this.tag[x - 1][y] == this.free) {
      this._add_neighbor(neighbors, x - 1, y)
    }
    return neighbors
  }

  _get_wall(current, neighbor) {
    let wall = null
    if (current.x == neighbor.x && current.y > neighbor.y) {
      wall = new Wall(current.x, current.y, this.H)
    }
    if (current.x < neighbor.x && current.y == neighbor.y) {
      wall = new Wall(current.x + 1, current.y, this.V)
    }
    if (current.x == neighbor.x && current.y < neighbor.y) {
      wall = new Wall(current.x, current.y + 1, this.H)
    }
    if (current.x > neighbor.x && current.y == neighbor.y) {
      wall = new Wall(current.x, current.y, this.V)
    }
    return wall == null ? null : wall.toString()
  }

  create() {
    let wall_removed = new Array()
    while (true) {
      let tmp_index = this._get_random(this.visited.length)
      let tmp_node = this.visited[tmp_index]
      let neighbor_num = tmp_node.neighbors.length
      let neighbor_index = this._get_random(neighbor_num)
      let neighbor = tmp_node.neighbors[neighbor_index]
      let wall = this._get_wall(tmp_node.v, neighbor)
      if (wall == null) {
        console.log("error")
        break
      }
      wall_removed.push(wall)
      if (neighbor.x == this.grid_num - 1 && neighbor.y == this.grid_num - 1) {
        break
      }
      let neighbors = this._get_neighbors(neighbor.x, neighbor.y)
      if (neighbors.length > 0) {
        this.visited.push(new Node(neighbor, neighbors))
      }
      tmp_node.neighbors.splice(neighbor_index, 1)
      if (tmp_node.neighbors.length == 0) {
        this.visited.splice(tmp_index, 1)
      }
    }
    return wall_removed
  }
}